/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tutorials;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 *
 * @author timon
 */
public class GridListenerTutorial {
  
  private static final int TILE_WIDTH = 32;
  private static final int TILE_HEIGHT = 32;
  
  /**
   * This panel is aware of mouse movement, and highlights the 
   * current grid tile that contains the mouse pointer.
   */
  static class ListenerDisplayPanel extends JPanel {

    // Private member variables
    private int mapWidth = 50; // Width of the map (in tiles)
    private int mapHeight = 50; // Length of the map (in tiles)

    // The point (in grid format, not pixel) currently highligted
    private Point currentlyAt = new Point(0,0);

    /**
     * CONSTRUCTOR (Default)
     */
    public ListenerDisplayPanel() {

      // Set the dimensions of the panel.
      setPreferredSize(new Dimension(
              mapWidth * TILE_WIDTH,
              mapHeight * TILE_HEIGHT));

      // Add the mouse listener, which will process the mouse movement
      // and record the current tile being highlighted
      addMouseMotionListener(new MouseMotionListener() {

        @Override
        public void mouseDragged(MouseEvent e) {
          // No code here.
        }

        @Override
        public void mouseMoved(MouseEvent e) {

          // Get the point where the mouse is located, in pixels,
          // relative to this component.
          Point relativePoint = e.getPoint();

          // Translate the relativePoint into a point relative to 
          // the grid 
          Point gridPoint = mouseAtComponent_ToGrid(relativePoint);

          // Assign this grid point to the currentlyAt variable, 
          // refreshing the currently selected tile space in 
          // memory.
          currentlyAt = gridPoint;

          // Refresh the invoking object and repaint the panel
          Component source = (Component) e.getSource();
          repaint();
          source.validate();
        }
      });

      setVisible(true);
    }

    /**
     * Allows calls to pass MouseEvents into this panel's
     * MouseMotionListener.
     * 
     * @param e 
     *   The MouseEvent that was triggered by user action.
     */
    public void mouseMoved(MouseEvent e) {
      processMouseMotionEvent(e);
    }
    
    /**
     * Translates the position of the mouse point (in pixel units)
     * into a grid position within a map.
     * 
     * @param mouseAt
     *   The position of the mouse in Point format.  You can get this 
     *     from the e.getPoint() command of a MouseEvent object.
     * 
     * @return 
     *   The currently hovered-o'er grid. 
     */
    private Point mouseAtComponent_ToGrid(Point mouseAt) {
  
      // divide the point by the tile size
      return new Point(
        (int) mouseAt.x / TILE_WIDTH,
        (int) mouseAt.y / TILE_HEIGHT); 
    }
    
    /**
     * Draws our graphics on the panel
     * 
     * @param g 
     *   The graphics component, which is something like the canvas
     *   you're painting on.
     */
    protected void paintComponent(Graphics g) {
             // Prevents images from getting gunky / forces full redraw
             super.paintComponent(g);

             // Initialize brush
             g.setColor(Color.red);

             // Draw a checkerboard on the screen based on height / weight value
             for (int x = 0 ; x < mapWidth ; x++) {
                 for (int y = 0 ; y < mapHeight ; y++) {

                     if ( (0 == x % 2) && 0 == (y % 2) ||
                             (x % 2 > 0) && (y % 2 > 0  )) {
                     // draw a 32 x 32 rectangle
                     g.drawRect(x * TILE_WIDTH, y * TILE_HEIGHT, 
                             TILE_WIDTH, TILE_HEIGHT);
                     }
                     else
                     {
                         g.fillRect(x * TILE_WIDTH, y * TILE_HEIGHT,
                                 TILE_WIDTH, TILE_HEIGHT);
                     }
                }
            }

             // Draw a green box around currently highligted square.
             // Drawing two lines will thicken the line, making it
             // more visible.
             g.setColor(Color.green);
             g.drawRect(
                     currentlyAt.x * TILE_WIDTH, 
                     currentlyAt.y * TILE_HEIGHT,
                     TILE_WIDTH, TILE_HEIGHT);
             g.drawRect(
                     (currentlyAt.x * TILE_WIDTH) + 1,
                     (currentlyAt.y * TILE_HEIGHT) + 1,
                     TILE_WIDTH - 2, TILE_HEIGHT - 2);
        }

    }
  
  /**
   *  We'll use this frame to show our display panel within a
   *  scroll panel.
   */
  static class PanelDisplayFrame extends JFrame {
    
    // Declare our listener panel and new Scroll pane as members.
    ListenerDisplayPanel displayPanel = new ListenerDisplayPanel();
    JScrollPane scrollPane = new JScrollPane();
    
    /**
     * CONSTRUCTOR (default)
     */
    public PanelDisplayFrame() {
      
      // Instantiate the scroll pane containing our display panel.
      scrollPane = new JScrollPane(displayPanel);
      
      // Update the scrollPane UI to prevent weird updating effects.
      scrollPane.updateUI();
      
      // Set up our scroll pane on the main panel.
      setLayout(new BorderLayout());
      add(scrollPane);
    }
  }
    
  public static void main(String[] args) {
    
    // Intantiate , setup and display our frame.
    PanelDisplayFrame frame = new PanelDisplayFrame();
    
    frame.setSize(600,400);
    frame.setTitle("Grid Listener Tutorial");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
  
  
}
